package com.ferry.transport.netty.proxy;

import com.ferry.common.util.Requires;
import com.ferry.registry.domain.service.ServiceMetaData;
import com.ferry.serial.api.SerializerType;
import com.ferry.transport.api.Directory;
import com.ferry.transport.api.UnResolvedAddress;
import com.ferry.transport.netty.consumer.Connector;
import com.ferry.transport.netty.consumer.FailStrategy;
import com.ferry.transport.netty.consumer.InvokeType;
import com.ferry.transport.netty.consumer.LbType;
import com.google.common.collect.Lists;

import java.util.Collections;
import java.util.List;

/**
 * Created by daiyong
 */
public class ProxyFactory<T> {

	private Class<T> interfaceClass;
	private String group;
	private String providerName;
	private String version;
	private SerializerType serializerType;
	private LbType lbType;
	private List<UnResolvedAddress> addresses;
	private InvokeType invokeType;
	private long timeout;
	private FailStrategy failStrategy;
	private int retries;
	private Connector connector;
	private String appName;


	//构造函数

	public ProxyFactory() {}

	private ProxyFactory(Class<T> interfaceClass) {
		this.interfaceClass = interfaceClass;
	}

	public static <T> ProxyFactory<T> factory(Class<T> interfaceClass) {
		ProxyFactory<T> factory = new ProxyFactory<T>(interfaceClass);
		// 初始化数据
		factory.addresses = Lists.newArrayList();
		return factory;
	}



	public Class<T> getInterfaceClass() {
		return interfaceClass;
	}

	public ProxyFactory<T> interfaceClass(Class<T> interfaceClass) {
		this.interfaceClass = interfaceClass;
		return this;
	}

	public ProxyFactory<T> group(String group) {
		this.group = group;
		return this;
	}

	public ProxyFactory<T> providerName(String providerName) {
		this.providerName = providerName;
		return this;
	}

	public ProxyFactory<T> version(String version) {
		this.version = version;
		return this;
	}

	public ProxyFactory<T> directory(Directory directory) {
		return group(directory.getGroup())
				.providerName(directory.getServiceProviderName())
				.version(directory.getVersion());
	}

	public ProxyFactory<T> serializerType(SerializerType serializerType) {
		this.serializerType = serializerType;
		return this;
	}

	public ProxyFactory<T> loadBalancerType(LbType lbType) {
		this.lbType = lbType;
		return this;
	}

	public ProxyFactory<T> addProviderAddress(UnResolvedAddress... addresses) {
		Collections.addAll(this.addresses, addresses);
		return this;
	}

	public ProxyFactory<T> addProviderAddress(List<UnResolvedAddress> addresses) {
		this.addresses.addAll(addresses);
		return this;
	}

	public ProxyFactory<T> invokeType(InvokeType invokeType) {
		this.invokeType = invokeType;
		return this;
	}

	public ProxyFactory<T> timeout(long timeout) {
		this.timeout = timeout;
		return this;
	}

	public ProxyFactory<T> failStrategy(FailStrategy failStrategy) {
		this.failStrategy = failStrategy;
		return this;
	}

	public ProxyFactory<T> failoverRetries(int retries) {
		this.retries = retries;
		return this;
	}

	public ProxyFactory<T> connector(Connector connector) {
		this.connector = connector;
		return this;
	}
	public ProxyFactory<T> appName(String appName) {
		this.appName = appName;
		return this;
	}

	public T newProxyInstance() {

		//服务元数据
		ServiceMetaData serviceMetaData = new ServiceMetaData(
				group,
				providerName,
				version
		);

		Object handler = null;
		switch (invokeType) {
			case SYNC :
				handler = new JdkProxyHandler(
						appName,
						serviceMetaData,
						retries,
						failStrategy,
						lbType,
						connector,
						serializerType
				);
				break;
			case ASYNC:
				//不知道怎么实现
				break;
			default:
				throw new IllegalArgumentException("invokeType not exists");
		}
		return new JdkProxy().newProxy(interfaceClass, handler);
	}



}
